﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace DumpMe
{
    public static class MiniDumpWriterEx
    {
        public enum ExceptionInfo
        {
            None,
            Present
        }

        // Pack = 4 is important, to align the data for x64, So it works also for x64
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct MiniDumpExceptionInformation
        {
            public uint ThreadId;

            public IntPtr ExceptionPointers;

            [MarshalAs(UnmanagedType.Bool)]
            public bool ClientPointers;

        }
        // Overload requiring MiniDumpExceptionInformation
        [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
        static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);

        [DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
        static extern uint GetCurrentThreadId();


        public static bool WriteEx(SafeHandle fileHandle, MiniDumpWriter.MINIDUMP_TYPE options, ExceptionInfo exceptionInfo)
        {
            Process currentProcess = Process.GetCurrentProcess();

            IntPtr currentProcessHandle = currentProcess.Handle;

            uint currentProcessId = (uint)currentProcess.Id;

            MiniDumpExceptionInformation exp;

            exp.ThreadId = GetCurrentThreadId();

            exp.ClientPointers = false;

            exp.ExceptionPointers = IntPtr.Zero;

            if (exceptionInfo == ExceptionInfo.Present)
            {
                exp.ExceptionPointers = System.Runtime.InteropServices.Marshal.GetExceptionPointers();
            }

            return MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, ref exp, IntPtr.Zero, IntPtr.Zero);
        }
    }
}
